package com.zhr.util;

import java.io.StringReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;

import com.zhr.bean.Article;
import com.zhr.bean.Music;
import com.zhr.server.WeixinRequest;
import com.zhr.server.WeixinResponse;

public class XmlUtil {

	public static <T> String toXml(T t) {
		return toXml(t, "xml");
	}
	
	private static <T> String toXml(T t,String head){
		if(null == t){
			return "";
		}
		StringBuilder sb = new StringBuilder();
		sb.append(String.format("<%s>", head)).append("\n");
		if(t instanceof Collection<?>){
			Collection<?> collection = (Collection<?>) t;
			for (Object object : collection) {
				sb.append(toXml(object, "item"));
			}
		}else{
			Class<?> clazz = t.getClass();
			Method[] methods = clazz.getMethods();
			try {
				for (Method method : methods) {
					String methodName = method.getName();
					if (methodName.startsWith("get")) {
						String key = methodName.substring(3);
						Method setMethod = null;
						try {
							setMethod = clazz.getMethod("set" + key, method.getReturnType());
						} catch (Exception e) {
							// TODO: handle exception
						}
						if(null != setMethod){
							Object value = method.invoke(t);
							if (method.getReturnType() == String.class) {
								try {
									String stringValue = (String) method.invoke(t);
									if(null != stringValue){
										try {
											Integer.parseInt(stringValue);
											sb.append(String.format(
													"<%s>%s</%s>\n", key, stringValue,
													key));
										} catch (Exception e) {
											sb.append(String.format(
													"<%s><![CDATA[%s]]></%s>\n", key, stringValue,
													key));

										}
									}
								} catch (Exception e) {
									e.printStackTrace();
								}
							}else {
								sb.append(toXml(value, key));
							}
						}
					}
				}
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		}
		sb.append(String.format("</%s>\n", head));
		return sb.toString();
	}
	
	public static void main(String[] args) {
		WeixinResponse response = new WeixinResponse();
		Music music = new Music();
		response.setMusic(music);
		List<Article> articles = new ArrayList<Article>();
		articles.add(new Article());
		articles.add(new Article());
		response.setArticles(articles );
		String xml = response.toString();
		System.out.println(xml);
	}

	public static <T> void fillBean(String xml, T t) {
		SAXReader reader = new SAXReader();
		Document doc;
		try {
			doc = reader.read(new StringReader(xml));
			Method[] methods = WeixinRequest.class.getMethods();
			for (Method method : methods) {
				String methodName = method.getName();
				if (methodName.startsWith("set")) {
					String key = methodName.substring(3);
					if (method.getParameterTypes().length == 1
							&& method.getParameterTypes()[0] == String.class) {
						try {
							method.invoke(t, doc.getRootElement().valueOf(key));
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}

	public static <T> T toBean(String xml, Class<T> clazz) {
		T t = null;
		try {
			t = clazz.newInstance();
			fillBean(xml, t);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return t;
	}

}
